package com.aldobucchi.ds.container
{
	
	import flash.utils.Dictionary;
	
	import com.aldobucchi.ds.DataStructureDiff;
	import com.aldobucchi.ds.container.utils.MultiplicityChange;
	import com.aldobucchi.ds.container.zet.IRSet;
	import com.aldobucchi.ds.container.zet.IRWSet;
	import com.aldobucchi.ds.container.zet.impl.RWDictionarySet;


	/**
	 * 
	 * 
	 * @author aldo.bucchi@gmail.com
	 * 
	 */
	public class ContainerDiff extends DataStructureDiff
	{
		
		
		private var _multiplicityChanges:Dictionary;
		/**
		 * 
		 * 
		 * 
		 * @return 
		 * 
		 */		
		public function get multiplicityChanges( ):Dictionary
		{
			return _multiplicityChanges;
		}
		
		
		
		


		private var _addedElements:IRWSet = null;
		/**
		 * 
		 * These elements recently became members of the Bag ( or Set )
		 * 
		 * @return 
		 * 
		 */
		public function get addedElements( ):IRSet
		{
			lazyInit( );
			return _addedElements;
		}





		private var _removedElements:IRWSet = null;
		/**
		 * 
		 * These elements are no longer members of the Bag.
		 * Their multiplicity dropped to zero.
		 * 
		 * @return 
		 * 
		 */
		public function get removedElements( ):IRSet
		{
			lazyInit( );
			return _removedElements;
		}		
		
		
		
		
		
		
		

		public function ContainerDiff( multiplicityChanges:Dictionary )
		{
			_multiplicityChanges = multiplicityChanges;
		}
		
		




		/**
		 * 
		 * mimics the typical container.walk() function.
		 * function( element:*, multiplicityDelta:int )
		 * 
		 * The only difference is that the second parameter now represents a delta
		 * and can be negative
		 * 
		 * @param walkerFunction
		 * 
		 */
		public function walk( walkerFunction:Function ):void
		{
			
			for ( var e:* in _multiplicityChanges )
			{
				var mc:MultiplicityChange = _multiplicityChanges[ e ] as MultiplicityChange;
				walkerFunction.apply( null, [ e, mc.delta ] );							
			}
		
		}














		
		
		
		private var lazyInitReady:Boolean = false;
		
		// we calculate some properties lazily
		private function lazyInit( ):void
		{
			
			if ( lazyInitReady )
				return;
				
			_addedElements = new RWDictionarySet( );
			
			_removedElements = new RWDictionarySet( );
			
			
			for ( var e:* in _multiplicityChanges )
			{
				var mc:MultiplicityChange = _multiplicityChanges[ e ] as MultiplicityChange;			
				
				if ( mc.isAddition )
					_addedElements.add( e );
				
				if ( mc.isRemoval )
					_removedElements.add( e );
								
			}
			
			lazyInitReady = true;
		
		
		}
		
		
		
		
		

	}

}